package com.freak.kotlinfitnessserver.util

import com.freak.kotlinfitnessserver.constant.ByteConstant
import java.math.BigInteger
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.util.Arrays

/**
 * 字节数据相关操作类
 * @author freak
 * @since 2024-01-12
 */
object ByteUtil {
    const val TAG: String = "ByteUtil"

    val HEX_ARRAY = "0123456789ABCDEF".toCharArray()

    /**
     * int类型转2字节
     * @param byteArray 待发送的byte数组
     * @param value 待转换的int数据
     * @param position byte数组位置
     */
    fun intToTwoByteArray(byteArray: ByteArray, value: Int, position: Int) {
        if (position > byteArray.size) {
            LogUtil.i(TAG, "position is error")
            return
        }
        var tempPosition = position
        val lowByte = (value and ByteConstant.BYTE_0XFF).toByte() // 低字节部分
        val highByte = ((value shr 8) and ByteConstant.BYTE_0XFF).toByte() // 高字节部分
        byteArray[tempPosition] = lowByte
        tempPosition++
        byteArray[tempPosition] = highByte
    }

    fun intToThreeByteArray(byteArray: ByteArray, value: Int, position: Int) {
        if (position > byteArray.size) {
            LogUtil.i(TAG, "position is error")
            return
        }
        var tempPosition = position
        val byteHigh = (value ushr 16 and 0xFF).toByte() // 最高 8 位
        val byteMiddle = (value ushr 8 and 0xFF).toByte()  // 中间 8 位
        val byteLow = (value and 0xFF).toByte() // 最低 8 位
        byteArray[tempPosition] = byteLow
        tempPosition++
        byteArray[tempPosition] = byteMiddle
        tempPosition++
        byteArray[tempPosition] = byteHigh
    }

    /**
     * int类型转1字节
     * @param byteArray 待发送的byte数组
     * @param value 待转换的int数据
     * @param position byte数组位置
     */
    fun intToOneByteArray(byteArray: ByteArray, value: Int, position: Int) {
        if (position > byteArray.size) {
            LogUtil.i(TAG, "position is error")
            return
        }
        val lowByte = (value and ByteConstant.BYTE_0XFF).toByte() // 低字节部分
        byteArray[position] = lowByte
    }

    fun intToThreeByte(byteArray: ByteArray, value: Int, position: Int): ByteArray {
        val bytes = ByteArray(3) // 创建长度为3的ByteArray对象
        for (i in 0 until 3) {
            bytes[2 - i] =
                ((value shr (8 * i)) and ByteConstant.BYTE_0XFF).toByte() // 利用位移操作获取每个字节的值
        }
        return bytes
    }

    fun intToFourByteArray(byteArray: ByteArray, value: Int, position: Int) {
        if (position > byteArray.size) {
            LogUtil.i(TAG, "position is error")
            return
        }
        for (i in 0 until 4) {
            // 利用位移操作获取每个字节的值
            byteArray[3 - i] = ((value shr (8 * i)) and ByteConstant.BYTE_0XFF).toByte()
        }
    }

    /**
     * 连续转换 int类型转2字节
     * @param byteArray 待发送的byte数组
     * @param value 待转换的int数组数据
     * @param position byte数组位置
     * @param valuePosition int数组的起始位置
     * @param paraCount 参数个数
     */
    fun moreIntToTwoByteArray(
        byteArray: ByteArray,
        value: IntArray,
        valuePosition: Int,
        position: Int,
        paraCount: Int
    ) {
        if (position >= byteArray.size) {
            LogUtil.i(TAG, "position is error")
            return
        }
        if (position + paraCount * 2 >= byteArray.size) {
            LogUtil.i(TAG, "paraCount is error")
            return
        }
        var tempPosition = position
        var tempValuePosition = valuePosition
        for (index in 0 until paraCount step 1) {
            val lowByte = (value[tempValuePosition] and ByteConstant.BYTE_0XFF).toByte() // 低字节部分
            val highByte =
                ((value[tempValuePosition] shr 8) and ByteConstant.BYTE_0XFF).toByte() // 高字节部分
            byteArray[tempPosition] = lowByte
            tempPosition++
            byteArray[tempPosition] = highByte
            tempPosition++
            tempValuePosition++
        }
    }

    /**
     * 连续转换 int类型转1字节
     * @param byteArray 待发送的byte数组
     * @param value byte数组位置
     * @param valuePosition int数组的起始位置
     * @param position byte数组位置
     * @param paraCount 参数个数
     */
    fun moreIntToOneByteArray(
        byteArray: ByteArray,
        value: IntArray,
        valuePosition: Int,
        position: Int,
        paraCount: Int
    ) {
        if (position >= byteArray.size || (position + paraCount * 2) >= byteArray.size) {
            LogUtil.i(TAG, "position is error")
            return
        }
        var tempPosition = position
        var tempValuePosition = valuePosition
        for (index in 0 until paraCount step 1) {
            val lowByte = (value[tempValuePosition] and ByteConstant.BYTE_0XFF).toByte() // 低字节部分
            byteArray[tempPosition] = lowByte
            tempPosition++
            tempValuePosition++
        }
    }

    /**
     * int类型转1字节byte
     * @param num 数字0-256
     */
    fun convertToOneByteLittleEndian(num: Int): Byte {
        val byteArray = ByteBuffer.allocate(Int.SIZE_BYTES)
            .order(ByteOrder.LITTLE_ENDIAN)// 设置字节顺序为小字节序
            .putInt(num)// 写入int值到ByteBuffer
            .array() // 创建一个长度为4的byte数组并设置顺序为小字节序
        return byteArray[0] // 返回第一个元素作为结果
    }

    /**
     * int类型转2字节byte
     * @param num 数字0-65535
     */
    fun convertToTwoByteLittleEndian(num: Int): ByteArray {
        val bytes = ByteBuffer.allocate(Int.SIZE_BYTES)
            .order(ByteOrder.LITTLE_ENDIAN)// 设置字节顺序为小字节序
            .putInt(num)// 写入int值到ByteBuffer
            .array()// 创建一个长度为4的byte数组并设置顺序为小字节序
        return Arrays.copyOfRange(bytes, 0, 2) // 只取前两个字节作为结果
    }

    /**
     * int类型转4字节byte
     */
    fun convertToFourByteLittleEndian(num: Int): ByteArray {
        val bytes = ByteBuffer.allocate(Int.SIZE_BYTES)
            .order(ByteOrder.LITTLE_ENDIAN)// 设置字节顺序为小字节序
            .putInt(num)// 写入int值到ByteBuffer
            .array()// 创建一个长度为4的byte数组并设置顺序为小字节序
        return bytes // 返回全部字节作为结果
    }

    /**
     * int类型转1字节byte 小端序
     * @param num 数字0-256
     */
    fun convertToOneByteLittleEndianWithDisplacement(num: Int): ByteArray {
        val lowByte = (num and 0xFF).toByte() // 低字节部分
        return byteArrayOf(lowByte)
    }

    /**
     * int类型转2字节byte 小端序
     * @param num 数字0-65535
     */
    fun convertToTwoByteLittleEndianWithDisplacement(num: Int): ByteArray {
        val lowByte = (num and 0xFF).toByte() // 低字节部分
        val highByte = ((num shr 8) and 0xFF).toByte() // 高字节部分
        return byteArrayOf(lowByte, highByte)
    }

    /**
     * int类型转4字节byte 小端序
     * @param num 数字0-65535
     */
    fun convertToFourByteLittleEndianWithDisplacement(num: Int): ByteArray {
        val byteArray = ByteArray(4) // 创建长度为4的byte数组
        for (i in 0 until 4) {
            // 利用位移操作获取每个字节的值
            byteArray[3 - i] = ((num shr (8 * i)) and ByteConstant.BYTE_0XFF).toByte()
        }
        return byteArray
    }

    /**
     * int类型转1字节byte 大端序
     * @param num 数字0-256
     */
    fun convertToOneByteBigEndianWithDisplacement(num: Int): ByteArray {
        val byteValue: Byte = ((num shr 8) and 0xFF).toByte() // 右移8位后取低8位
        return byteArrayOf(byteValue)
    }

    /**
     * int类型转2字节byte 大端序
     * @param num 数字0-65535
     */
    fun convertToTwoByteBigEndianWithDisplacement(num: Int): ByteArray {
        val lowByte = (num and 0xFF).toByte() // 低字节部分
        val highByte = ((num shr 8) and 0xFF).toByte() // 高字节部分
        return byteArrayOf(highByte, lowByte)
    }


    fun hexToString(hexString: String): String {
        val bigInt = BigInteger("0x$hexString", 16) // 将十六进制字符串转换为大整数对象
        return bigInt.toString() // 返回大整数的字符串表示形式
    }

    fun bytesToHexString(bytes: ByteArray): String {
        val hexChars = CharArray(bytes.size * 2)
        for (index in bytes.indices) {
            val value = bytes[index].toInt() and 0xFF
            hexChars[index * 2] = HEX_ARRAY[(value ushr 4)]
            hexChars[index * 2 + 1] = HEX_ARRAY[value and 0x0F]
        }
        return String(hexChars)
    }
    fun byteArrayToStringValue(value: ByteArray, offset: Int): String? {
        if (offset > value.size) return null
        val strBytes = ByteArray(value.size - offset)
        for (i in 0 until value.size - offset) {
            strBytes[i] = value[offset + i]
        }
        return String(strBytes)
    }
}